<?php


namespace App\Order\Repository;


use App\Activity\Model\GroupOrder;
use App\Common\Constants\ErrorCode;
use App\Common\Constants\Stakeholder;
use App\Common\Job\LogJob;
use App\Order\Job\CancelOrderJob;
use App\Order\Model\OrderExpressModel;
use App\Order\Model\OrderGoodsModel;
use App\Order\Model\OrderLogModel;
use App\Order\Model\OrderModel;
use App\Order\Model\OrderRefundModel;
use App\Order\Service\Order\OrderMiniService;
use Hyperf\AsyncQueue\Driver\DriverFactory;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\Model;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\ApplicationContext;

class OrderRepository implements BaseRepositoryInterface
{


    /**
     * 15 分钟取消未支付订单
     */
    const CANCEL_ORDER_SECOND = 900;
    protected $driver;
    protected $driverLog;
    protected $container;

    public function __construct(DriverFactory $driverFactory)
    {
        $container = ApplicationContext::getContainer();
        $this->container = $container;
        $this->driver = $driverFactory->get('order');
        $this->driverLog = $driverFactory->get('log');
    }

    public function delete()
    {
        // TODO: Implement delete() method.
        var_dump("222");
    }

    /**
     * 更新订单
     *
     * Author: mengchenchen
     * Created_at: 2021/1/6 0006 14:42
     * Updated_at: 2021/1/6 0006 14:42
     *
     * @param array $where
     * @param array $data
     * @return bool
     */
    public function update($where = [], $data = []): bool
    {
        $order = $this->findFirst($where);
        if ($order instanceof OrderModel) {
            return $order->fill($data)->save($data);
        }
        return false;
    }

    public function getList()
    {
        // TODO: Implement getList() method.
    }

    public function findFirst(array $where = [], array $field = ['*'])
    {
        return OrderModel::query()
            ->select($field)
            ->where($where)
            ->first();
    }

    /***
     *
     * 立即购买获取订单信息
     * @param string $order_no
     * @return array
     */
    public function getOrderInfo(string $order_no)
    {
        $order = OrderModel::query()->from('store_order as o')
            ->join('store_order_goods as g', 'g.order_no', '=', 'o.order_no')
            ->where(['o.order_no' => $order_no])
            ->select(['g.number', 'o.goods_price', 'o.total_price'])
            ->first();
        return $order?$order->toArray():[];
    }
    /**
     * 分享订单详情
     * @param int $mid
     * @param string $order_no
     * @return array
     */
    public function shareOrderDetail(int $mid, string $order_no)
    {

        $orderDetail = OrderModel::where(['mid' => $mid, 'order_no' => $order_no, 'is_pay' => 1])->select(['order_no', 'shop_id', 'leader_id', 'platform_type', 'total_price', 'pay_at', 'pay_type','order_type','order_source','status'])->first();
        if ($orderDetail) {
            $orderDetail['group_num'] = '';
            if($orderDetail['order_type']==OrderMiniService::ORDER_TYPE_6){
                $orderDetail['group_num'] = GroupOrder::where(['order_no'=>$orderDetail['order_no']])->value('group_num');
            }
            return $orderDetail->toArray();
        } else {
            return [];
        }
    }

    /**
     *
     * 获取分享订单、商品列表
     * @param string $order_no
     * @return array|\Hyperf\Database\Model\Builder|\Hyperf\Database\Model\Model|object|null
     */
    public function getShareGoods(string $order_no)
    {
        $orderDetail = OrderModel::where(['order_no' => $order_no, 'is_pay' => 1])
            ->with(['goods' => static function ($query) {
                $query->groupBy(['group_id','goods_id'])->select(['goods_id', 'group_id', 'activity_goods_id','order_no']);
            }])
            ->select(['order_no', 'shop_id', 'leader_id', 'platform_type', 'total_price', 'pay_at', 'pay_type', 'order_source', 'status', 'order_type'])->first();
        if ($orderDetail) {
            $orderDetail = $orderDetail->toArray();
        } else {
            $orderDetail = [];
        }
        return $orderDetail;
    }
    /**
     *
     * 写入订单
     * @param int $mid
     * @param array $orderData
     * @param array $orderGoods
     * @param array $param
     * @param int $type
     * @param string $orderNo
     * @param array $orderExpressInsertData
     * @param array $cartIds
     * @return array
     * @author lulongfei
     */
    public function saveOrder(int $mid,array $orderData,array $orderGoods,array $param,int $type,string $orderNo,array $orderExpressInsertData=[],array $cartIds=[])
    {
        Db::beginTransaction();
        try {
            OrderModel::query()->insert($orderData);
            if ($orderExpressInsertData) {
                OrderExpressModel::query()->insert($orderExpressInsertData);
            }
            OrderGoodsModel::query()->insert($orderGoods);
            if($cartIds){
                $this->container->get(OrderMiniService::class)->delCart($cartIds,$mid);
            }
            Db::commit();
            $this->driver->push(new CancelOrderJob(['order_no' => $orderNo]), self::CANCEL_ORDER_SECOND);
            $this->saveOrderLog('info', $param, $type, $orderNo);
            return ['code' => ErrorCode::SUCCESS, 'order_no' => $orderNo];
        } catch (\Throwable $ex) {
            Db::rollback();
            $this->saveOrderLog('error', $param, $type, $ex->getMessage());
            return ['code' => ErrorCode::NOT_IN_FORCE,'msg'=>$ex->getMessage()];
        }
    }
    /**
     * 记录日志
     * $type=0及时达 $type =1次日达
     * @param string $event
     * @param array $param
     * @param int $type
     * @param string $response
     * @return bool
     */
    public function saveOrderLog(string $event, array $param, int $type, string $response)
    {
        $data = ['type' => 2, 'data' => ['event' => $event, 'params' => json_encode($param), 'order_type' => $type, 'response' => $response, 'created_at' => date('Y-m-d H:i:s')]];
        $this->driverLog->push(new LogJob($data), 1);
    }
    /**
     *
     * 校验秒杀、限购已购买商品数量
     * @param int $goods_id
     * @param int $activity_goods_id
     * @param int $mid
     * @return int|mixed
     * @author lulongfei
     */
    public function getSeckillOrderNum(array $activity_goods_id, int $mid)
    {
        return OrderModel::from('store_order as o')->join('store_order_goods as g', 'o.order_no', '=', 'g.order_no')
            ->whereRaw('o.status <> '.OrderMiniService::ORDER_STATUS_5)
            ->where(['o.mid' => $mid,'o.is_pay'=>1])
            ->whereIn('g.activity_goods_id',$activity_goods_id)
            ->groupBy(['g.activity_goods_id'])
            ->selectRaw('sum(g.number - g.refund_number - g.shop_refund_number) as num,activity_goods_id')
            ->get()->toArray();
    }
    /**
     * 店铺当日下单序列数
     * @param $shopId
     * @return int
     */
    public static function getToDayOrderSerialNumByShopId(int $shopId)
    {
        $todayStart = date('Y-m-d', time());
        $orderCount = OrderModel::query()->where('create_at', '>', $todayStart)->where(['shop_id' => $shopId])->count();
        return $orderCount + 1;
    }
    /**
     * 团购售后订单
     * @param array $param
     * @param array $where
     * @param array|null $in
     * @param array|string[] $field
     * @return Builder[]|\Hyperf\Database\Model\Collection|\Hyperf\Database\Query\Builder[]|\Hyperf\Utils\Collection
     */
    public function miniCommonRefundOrderList(array $param, array $where, array $field, ?array $in = null)
    {
        return OrderRefundModel::query()
            ->from('store_order_refund as refund')
            ->leftJoin('store_order as order', 'refund.order_no', '=', 'order.order_no')
            ->with('refundGoods:order_no,refund_no,goods_logo,goods_title,goods_spec,selling_price,refund_price,refund_number')
            ->select($field)
            ->where($where)
            ->when($in, function ($query, $in) {
                foreach ($in as $k => $v) {
                    $query->whereIn($v[0], $v[1]);
                }
                return $query;
            })
            ->latest('create_at')
            ->when($param['perpage'] ?? 0, function ($query, $perPage) {
                return $query->paginate((int)$perPage);
            }, function ($query) {
                return $query->get();
            });
    }
    /**
     * 拼团订单列表
     * @param array $param
     * @param array $where
     * @param array|string[] $field
     * @param array|null $in
     * @return Builder[]|\Hyperf\Database\Model\Collection
     */
    public function miniCommonOrderList(array $param, array $where, array $field = ['*'], ?array $in = null)
    {
        return OrderModel::query()->from('store_order as order')->leftJoin('store_shop as shop', 'order.shop_id', '=', 'shop.shop_id')->with('goods:order_no,goods_id,goods_logo,goods_title,goods_spec,market_price as price_market,selling_price,activity_goods_id,group_id,number', 'member:mid,face_url')->select($field)->where($where)->when($in, function ($query, $in) {
            foreach ($in as $k => $v) {
                $query->whereIn($v[0], $v[1]);
            }
            return $query;
        })->latest('create_at')->when($param['perpage'] ?? 0, function ($query, $perPage) {
            return $query->paginate((int) $perPage);
        }, function ($query) {
            return $query->get();
        });
    }
    /**
     * 小程序-订单详情
     * @param array $where
     * @param array|string[] $field
     * @return Builder|Model|\Hyperf\Database\Query\Builder|object|null
     */
    public function orderDetail(array $where, array $field = ['*'])
    {
        $goodsFiled = [
            'order_no',
            'id',
            'goods_id',
            'goods_logo',
            'goods_title',
            'goods_spec',
            'selling_price',
            'activity_goods_id',
            'group_id',
            'number',
            'dis_price',
            'deductMoney',
            'goods_dis_price',
            'status',
            'market_price as price_market',
            'is_refund_status',
            '(case when is_refund_status=1 then (refund_number+shop_refund_number) when is_refund_status=2 then number else 0 end) as already_refund_num',
            '(case when is_refund_status=1 then (refund_number+shop_refund_number)*goods_dis_price  when is_refund_status=2 then dis_price else 0 end) as already_refund_amt'
        ];
        $detail = OrderModel::query()
            ->from('store_order as order')
            ->leftJoin('store_shop as shop', 'order.shop_id', '=', 'shop.shop_id')
            ->with(['goods' => function($query) use ($goodsFiled) {
                $query->selectRaw(implode(',', $goodsFiled));
            }])
            ->selectRaw(implode(',', $field))
            ->where($where)
            ->first()??[];
        if (!$detail) return $detail;
        if ($detail->is_pay == Stakeholder::ORDER_UNPAID) {
            $detail->time_remaining = strtotime($detail->create_at . ' +15 minute');
        }
        return $detail;
    }

    /**
     * 团长订单详情
     * @param array $where
     * @param array $orderField
     * @param array $orderGoodsField
     * @return Builder|Model|object|null
     */
    public function teamOrderDetail(array $where,array $orderField,array $orderGoodsField)
    {
        $orderDetail = OrderModel::query()
            ->with([
                'goods' => function ($query) use ($orderGoodsField) {
                    $query->select(
                        $orderGoodsField
                    );
                }
            ])
            ->select($orderField)
            ->where($where)
            ->first();
        return $orderDetail;
    }

    /**
     *
     *
     * 团长订单列表
     * @param array $where
     * @param array $whereIn
     * @param array $field
     * @param int $perPage
     * @return \Hyperf\Contract\LengthAwarePaginatorInterface
     */
    public function getTeamLeaderOrderList(array $where,array $whereIn,array $field,int $perPage)
    {
        $orderList = OrderModel::query()
            ->with([
                'goods' => function ($query) {
                    $query->select([
                        'goods_title',
                        'goods_spec',
                        'goods_logo',
                        'selling_price',
                        'market_price',
                        'number',
                        'take_num',
                        'order_no',
                        'id as order_goods_id'
                    ]);
                }
            ])
            ->select($field)
            ->where($where)
            ->whereIn('status', $whereIn)
            ->orderBy('create_at', 'desc')
            ->paginate($perPage);
        return $orderList;

    }


    /**
     *
     * 写入订单
     * @param int $mid
     * @param array $orderData
     * @param array $orderGoods
     * @param array $param
     * @param int $type
     * @param string $orderNo
     * @param array $orderExpressInsertData
     * @param array $cartIds
     * @return array
     * @author lulongfei
     */
    public function saveEntrustOrder(int $mid,array $orderData,array $orderGoods,array $param,int $type,string $orderNo,array $orderExpressInsertData=[])
    {
        Db::beginTransaction();
        try {

            OrderModel::query()->insert($orderData);
            if ($orderExpressInsertData) {
                OrderExpressModel::query()->insert($orderExpressInsertData);
            }
            OrderGoodsModel::query()->insert($orderGoods);
            Db::commit();
            $this->driver->push(new CancelOrderJob(['order_no' => $orderNo]), self::CANCEL_ORDER_SECOND);
            $this->saveOrderLog('info', $param, $type, $orderNo);
            return ['code' => ErrorCode::SUCCESS, 'order_no' => $orderNo];
        }catch (\Throwable $ex) {
            Db::rollback();
            $this->saveOrderLog('error', $param, $type, $ex->getMessage());
            return ['code' => ErrorCode::NOT_IN_FORCE];
        }
    }

    /**
     * 获取免单好友明细
     * @param array $where
     * @param array|string[] $field
     */
    public function getOrderSubDetail(array $where,array $field=['*'])
    {
        $order = OrderModel::from('store_order as o')
            ->join('store_member as m','o.mid','=','m.mid')
            ->where($where)
            ->select($field)
            ->get()
            ->each(function ($item){
                if(!$item->refund_at){
                    $item->refund_at = '';
                }
            })
            ->toArray();
        return $order;
    }
}
